package com.zmn.plat.admin.controller.pilot;


import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.dictionary.GlobalDict;
import com.zmn.common.dto.KvDTO;
import com.zmn.common.dto.VtDTO;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.manager.common.database.annotation.ReadOnlyConnection;
import com.zmn.plat.admin.controller.PlatBaseController;
import com.zmn.plat.business.interfaces.channel.ChannelBService;
import com.zmn.plat.business.interfaces.pilot.ChannelPriceCategoryBService;
import com.zmn.plat.common.constant.OnePriceConsts;
import com.zmn.plat.common.util.StringToArrayUtil;
import com.zmn.plat.manager.dictionary.ChannelDict;
import com.zmn.plat.manager.dictionary.OnePriceDict;
import com.zmn.plat.model.entity.channel.Channel;
import com.zmn.plat.model.entity.channel.ChannelIdAndName;
import com.zmn.plat.model.entity.channel.ChannelQuery;
import com.zmn.plat.model.entity.pilot.*;
import com.zmn.plat.model.vo.servcategory.ServAssCategoryVO;
import com.zmn.plat.services.interfaces.area.BaseAreaService;
import com.zmn.plat.services.interfaces.channel.ChannelService;
import com.zmn.plat.services.interfaces.pilot.ChannelPriceCategoryService;
import com.zmn.plat.services.interfaces.pilot.ChannelPriceCityService;
import com.zmn.plat.services.interfaces.pilot.ChannelPriceService;
import com.zmn.plat.utils.bean.BeanCopyUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.groupingBy;

/**
 * 渠道试点基础查询Controller
 *
 * @author yangshuangping
 * @since 2021-06-25 10:16:42
 */
@Slf4j
@RestController
@RequestMapping("/pilot/channel/price")
public class ChannelPriceListController extends PlatBaseController {
    /**
     * 省parentId
     */
    public static final int AREA_PARENTID = 1;

    @Resource
    private ChannelPriceService channelPriceService;

    @Resource
    private ChannelPriceCityService channelCityService;

    @Autowired
    private ChannelService channelService;

    @Autowired
    private ChannelBService channelBService;

    @Autowired
    private BaseAreaService baseAreaService;

    @Autowired
    private ChannelPriceCategoryService categoryService;

    @Autowired
    private ChannelPriceCategoryBService categoryBService;

    /**
     * 描述: 查询列表
     *
     * @author yangshuangping
     * @since 2021-06-25 10:16:42
     */
    @RequestMapping("/list")

    public ModelAndView list(@ModelAttribute ChannelPriceQuery query) {

        ModelAndView mav = new ModelAndView("pilot/list");

        try {
            List<ChannelPrice> items = new ArrayList<>();

            List<Integer> ids = getCityChannelPriceIds(query.getProvinceId(), query.getCityId());
            if (CollectionUtil.isNotNullOrEmpty(ids)) {
                query.setDelete(OnePriceConsts.PILOT_LOGICTODELETE_NORMAL);
                query.setChannelPriceIds(ids);
                items = channelPriceService.listPageByQuery(query);
            }
            mav.addObject("provinceList", getAreaList(AREA_PARENTID));
            mav.addObject("cityList", (query.getProvinceId() == null ? null : getAreaList(query.getProvinceId())));
            mav.addObject("channelList", channelService.listEnableRankTwoChannel());
            mav.addObject("typeList", OnePriceDict.getTypeList());
            mav.addObject("vo", query);
            mav.addObject("items", translateShowNane(items));

        } catch (Exception e) {
            log.error(e.toString(), e);
        }
        return mav;
    }

    /**
     * 描述: 新增配置
     *
     * @return modelAndView
     * @author yangshuangping
     * @since 2021/7/1 11:20
     */
    @RequestMapping(value = "add")
    public ModelAndView add() {

        ModelAndView mav = new ModelAndView("pilot/add");
        mav.addObject("typeList", OnePriceDict.getTypeList());
        mav.addObject("type", 1);

        return mav;
    }

    /**
     * 描述: 跳转到添加或者编辑页面
     *
     * @author yangshuangping
     * @since 2021-06-25 10:16:42
     */
    @RequestMapping("/addEditView")
    public ModelAndView info(ChannelPriceVO channelPriceVO) {

        ModelAndView mv = new ModelAndView("pilot/edit");
        return this.detailChannelPrice(mv, channelPriceVO);

    }


    /**
     * 描述: 渠道一口价详情
     *
     * @param channelPriceVO 详情页
     * @return ModelAndView 产品详情页面
     * @author yangshuangping
     * @since 2021/7/1 11:20
     */
    @RequestMapping("detail")
    public ModelAndView detail(ChannelPriceVO channelPriceVO) {

        ModelAndView mav = new ModelAndView("pilot/detail");
        return this.detailChannelPrice(mav, channelPriceVO);

    }

    /**
     * 检查城市ID是否已配置
     *
     * @param provinceId 省份ID
     * @param cityId     城市ID
     * @param channelId  渠道ID
     * @return ResponseDTO
     * @author yangshuangping
     * @since 2021/7/1 11:20
     */
    @RequestMapping(value = "checkCity")
    @ResponseBody
    @ReadOnlyConnection
    public ResponseDTO checkCity(Integer provinceId, Integer cityId, Integer channelId, Integer type) {

        if (NumberUtil.isNullOrZero(channelId)) {
            return ResponseDTO.success(true, "添加成功！");
        }

        ChannelPriceCityQuery query = new ChannelPriceCityQuery();
        query.setChannelPriceIdList(getChannelPriceIds(channelId, type));
        query.setProvinceId(provinceId);
        List<ChannelPriceCity> channelPriceCityList = channelCityService.listByQuery(query);

        boolean flag = false;
        String checkMsg = "已在其他配置项中开通，不支持重复选择！";

        for (ChannelPriceCity item : channelPriceCityList) {
            if (Objects.equals(item.getCityId(), cityId)) {
                flag = true;
            } else if (Objects.equals(item.getProvinceId(), provinceId) && item.getCityId() == null) {
                flag = true;
                checkMsg = "父级城市已在其他配置项中开通！";
            } else if (Objects.equals(item.getProvinceId(), provinceId) && cityId == null) {
                flag = true;
                checkMsg = "子级城市已在其他配置项中开通！";
            }
        }

        if (flag) {
            return ResponseDTO.fail(checkMsg);
        }

        return ResponseDTO.success(true, "添加成功！");
    }

    /**
     * 应用前台分类
     *
     * @param configId 配置ID
     * @param type     配置类型 1渠道配置 2城市配置
     * @param showType 产品分类 1后台 2前台
     * @return the model and view
     * @author xiangjunming
     * @since 2019/11/21
     */
    @RequestMapping(value = "serviceCategory")
    @ReadOnlyConnection
    public ModelAndView serviceCategory(String configId, Integer type, Integer showType) {

        ModelAndView mav = new ModelAndView("pilot/serviceCategory");

        List<KvDTO<Integer, String>> servCategorys;
        //新增的时候可能会同时对多个渠道设置
        List<Integer> configIds = StringToArrayUtil.convertStrsToList(configId);

        List<String> categIds = new ArrayList<>();
        if (type == GlobalConsts.NO && configIds.size() > GlobalConsts.NONE) {
            ChannelPrice price = channelPriceService.findById(configIds.get(GlobalConsts.NONE));
            servCategorys = channelBService.listAllLevelCategoryByChannelId(price.getChannelId(), showType);
        } else {
            servCategorys = listAllChildCategory(showType);
        }
        //新增时没有服务分类配置，则不需要回显

        if (configIds.size() > GlobalConsts.NONE) {
            ChannelPriceCategoryQuery query = new ChannelPriceCategoryQuery();
            query.setType(type);
            query.setShowType(showType);
            query.setConfigId(configIds.get(GlobalConsts.NONE));
            List<ChannelPriceCategory> serviceCategoryList = categoryService.listByQuery(query);

            categIds = serviceCategoryList.stream()
                    .map(p -> categoryBService.servToStr(p))
                    .collect(Collectors.toList());
        }
        if (servCategorys != null && servCategorys.size() > 0) {
            mav.addObject("currentServCategId", servCategorys.get(0).getKey());
        }
        mav.addObject("categIds", categIds);
        mav.addObject("servCategorys", servCategorys);
        mav.addObject("configId", configId);
        mav.addObject("type", type);
        mav.addObject("showType", showType);
        return mav;
    }

    /**
     * 描述: 根据渠道ID，类型 获取渠道试点配置ID
     *
     * @param channelId 渠道ID
     * @param type      类型
     * @return ids
     * @author yangshuangping
     * @since 2021/7/1 11:20
     **/
    protected List<Integer> getChannelPriceIds(Integer channelId, Integer type) {
        if (NumberUtil.isNullOrZero(channelId)) {
            return new ArrayList<>();
        }

        ChannelPriceQuery query = new ChannelPriceQuery();
        query.setChannelId(channelId);
        query.setType(type);
        query.setDelete(OnePriceConsts.PILOT_LOGICTODELETE_NORMAL);

        return Optional.ofNullable(channelPriceService.listByQuery(query)).orElse(new ArrayList<>())
                .stream()
                .map(ChannelPrice::getChannelPriceId)
                .collect(Collectors.toList()).stream()
                .distinct()
                .collect(Collectors.toList());
    }

    /**
     * 描述: 渠道试点执行城市获取渠道一口价的渠道配置ID
     *
     * @param provinceId 省份id
     * @param cityId     城市id
     * @return ids
     * @author yangshuangping
     * @since 2021/7/1 11:20
     **/
    protected List<Integer> getCityChannelPriceIds(Integer provinceId, Integer cityId) {

        ChannelPriceCityQuery cityQuery = new ChannelPriceCityQuery();
        cityQuery.setCityId(cityId);
        cityQuery.setProvinceId(provinceId);

        return Optional.ofNullable(channelCityService.listByQuery(cityQuery))
                .orElse(new ArrayList<>()).stream()
                .map(ChannelPriceCity::getChannelPriceId)
                .collect(Collectors.toList()).stream()
                .distinct()
                .collect(Collectors.toList());
    }

    /**
     * 值转换显示中文
     *
     * @param list list
     * @author yangshuang   ping
     * @since 2021-6-25 16:05:10
     */
    protected List<ChannelPriceVO> translateShowNane(List<ChannelPrice> list) {

        List<ChannelPriceVO> priceVOList = new ArrayList<>();
        // 根据渠道ID获取渠道名称
        List<Integer> channelIds = list.stream()
                .map(ChannelPrice::getChannelId)
                .collect(Collectors.toList());

        // 根据渠道id获取渠道名称
        Map<Integer, String> channelMap = Optional.ofNullable(channelService.listNameByChannelIds(channelIds))
                .orElse(new ArrayList<>()).stream()
                .collect(Collectors.toMap(ChannelIdAndName::getChannelId, ChannelIdAndName::getName));

        // 执行一口价城市 执行标准价城市
        List<Integer> channelPriceIds = list.stream()
                .map(ChannelPrice::getChannelPriceId)
                .distinct()
                .collect(Collectors.toList());

        Map<Integer, String> priceCities = cityIdAndNameMap(channelPriceIds, OnePriceConsts.EXECUTE_ONE_PRICE_CITY);
        Map<Integer, String> standardPriceCity = cityIdAndNameMap(channelPriceIds, OnePriceConsts.EXECUTE_STANDARD_PRICE_CITY);

        list.forEach(x -> {
            ChannelPriceVO priceVO = new ChannelPriceVO();
            BeanCopyUtils.copyProperties(x, priceVO);
            priceVO.setChannelName(channelMap.get(x.getChannelId()));
            priceVO.setCityPriceName(priceCities.get(x.getChannelPriceId()));
            priceVO.setCityBaseName(standardPriceCity.get(x.getChannelPriceId()));
            priceVOList.add(priceVO);
        });
        return priceVOList;
    }

    /**
     * 获取渠道试点执行城市名称
     *
     * @param channelPriceIds 试点渠道ID
     * @param type            类型：1.执行一口价城市,2.执行标准价城市
     * @return 省份名称或市名称
     * @author yangshuangping
     * @since 2021-6-25 16:05:10
     */
    protected Map<Integer, String> cityIdAndNameMap(List<Integer> channelPriceIds, Integer type) {

        return Optional.ofNullable(channelCityService.listNameByChannelPriceIds(channelPriceIds, type))
                .orElse(new ArrayList<>()).stream().distinct()
                .collect(Collectors.toMap(CityIdAndName::getCityId, CityIdAndName::getName));
    }

    /**
     * 获取地区列表
     *
     * @param parentId 父级ID
     * @return List<VtDTO>
     * @author yangshuangping
     * @since 2021-6-25 16:05:10
     */
    protected List<VtDTO> getAreaList(Integer parentId) {

        return Optional.ofNullable(baseAreaService.listByParentId(parentId))
                .map(p -> p.stream()
                        .map(t -> new VtDTO(t.getAreaId(), t.getName()))
                        .collect(Collectors.toList()))
                .orElse((List<VtDTO>) Collections.EMPTY_LIST);
    }

    /**
     * 描述: 加载添加编辑页面基础数据
     *
     * @param mav            视图对象
     * @param channelPriceVO VO
     * @return org.springframework.web.servlet.ModelAndView
     * @author yangshuangping
     * @since 2021-6-25 16:05:10
     **/
    private ModelAndView detailChannelPrice(ModelAndView mav, ChannelPriceVO channelPriceVO) {

        Integer channelPriceId = channelPriceVO.getChannelPriceId() == null ? 0 : channelPriceVO.getChannelPriceId();

        // 加载一口价城市数据
        if (channelPriceId > 0) {
            BeanUtils.copyProperties(channelPriceService.findById(channelPriceId), channelPriceVO);

            // 获取渠道试点执行城市查询
            ChannelPriceCityQuery query = new ChannelPriceCityQuery();
            query.setChannelPriceId(channelPriceId);
            List<ChannelPriceCity> channelPriceCityList = channelCityService.listByQuery(query);

            // 添加是否支持试点城市
            Map<Integer, List<ChannelPriceCity>> channelPriceCityTypeMap = channelPriceCityList.stream()
                    .collect(groupingBy(ChannelPriceCity::getType));
            mav.addObject("onePriceList", channelPriceCityTypeMap.get(OnePriceConsts.SUPPORT_CITY));
            mav.addObject("basePriceList", channelPriceCityTypeMap.get(OnePriceConsts.NOT_SUPPORT_CITY));
        }
        // 如果没有设置定金则默认为0

        channelPriceVO.setDeposit(NumberUtil.isNullOrZero(channelPriceVO.getDeposit()) ? null : channelPriceVO.getDeposit());

        if (NumberUtil.isNullOrZero(channelPriceVO.getDepositDeductionAmount())){
            channelPriceVO.setDepositDeductionAmount(null);
        }


        mav.addObject("depositList", OnePriceDict.getDepositList());
        mav.addObject("baseAreaList", getAreaList(AREA_PARENTID));
        mav.addObject("payTypeList", OnePriceDict.getPayTypeList());
        mav.addObject("statusList", OnePriceDict.getStatusList());
        mav.addObject("channelPriceVO", channelPriceVO);
        mav.addObject("channelList", channelService.listEnableRankTwoChannel());
        mav.addObject("typeList", OnePriceDict.getTypeList());

        return mav;
    }

    /**
     * 获取全部分类信息
     *
     * @param showType 产品分类 1后台 2前台
     * @return the list
     */
    @ReadOnlyConnection
    protected List<KvDTO<Integer, String>> listAllChildCategory(Integer showType) {

        List<ServAssCategoryVO> voList = channelBService.listServCategoryByShowType(showType);

        return channelBService.listAllChildCategory(voList);
    }
}

